package wangxiaotao.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import wangxiaotao.common.CommonResult;
import wangxiaotao.entity.Order;
import wangxiaotao.entity.alipay.AliPayRequest;
import wangxiaotao.entity.alipay.AliPayResponse;
import wangxiaotao.entity.alipay.CreateOrder;
import wangxiaotao.entity.schedule.TaskEntity;
import wangxiaotao.enums.OrderStatue;
import wangxiaotao.task.ScheduledTask;
import wangxiaotao.tool.AliPayTool;
import wangxiaotao.utils.JWTUtils;
import wangxiaotao.utils.NoUtils;
import wangxiaotao.utils.RedisUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/pay")
public class PayController extends BaseController{
    private final ScheduledTask scheduledTask;

    @RequiresAuthentication
    @PostMapping("/order")
    public CommonResult pay(@Validated @RequestBody CreateOrder createOrder) throws AlipayApiException {
        AliPayRequest aliPayRequest = createOrder.getAliPayRequest();
        //订单请求数据处理
        String orderNo = NoUtils.setOrderNo();
        aliPayRequest.setOut_trade_no(orderNo);
        //向支付宝发生订单创建申请
        String pay = AliPayTool.pay(aliPayRequest);
        String id = JWTUtils.getClaimByName((String) SecurityUtils.getSubject().getPrincipal(), "id");

        //内部订单产生
        Order order = new Order();
        order.setUserId(Integer.parseInt(id))
                .setOrderRoomTypeId(createOrder.getRoomTypeId())
                .setOrderName(createOrder.getName())
                .setOrderEmail(createOrder.getEmail())
                .setOrderPhone(createOrder.getPhone())
                .setOrderNo(orderNo)
                .setOrderStatue(OrderStatue.WAITPAY)
                .setOrderNote(createOrder.getRemark());
        orderService.save(order);

        //订单编号存储到redis 时间为30分钟
        RedisUtils.set(orderService.getRealOrderCancelPrefix(orderNo), orderNo, orderService.getOrderCancelTime());

        //轮询订单状态 1s 一次
        Map<String, Object> properties = new HashMap<>();
        //订单参数传递
        properties.put("out_trade_no",orderNo);
        properties.put("userId",id);
        //定时任务创建
        List<TaskEntity> list = Collections.singletonList(
                new TaskEntity(1, "订单状态轮询", "0/1 * * * * ?",properties)
        );
        //开启定时任务
        scheduledTask.refresh(list);
        return CommonResult.success(pay);
    }

    /**
     * 支付完成 支付宝异步返回
     * @param res
     * @throws AlipayApiException
     * @throws IOException
     */
    @PostMapping("/notify")
    public void notifyUrl(@RequestParam Map<String,Object> res) throws AlipayApiException, IOException {
        AliPayResponse aliPayResponse = JSON.parseObject(JSON.toJSONString(res), AliPayResponse.class);
        //删除redis里面的自动取消的订单
        RedisUtils.remove(orderService.getRealOrderCancelPrefix(aliPayResponse.getOut_trade_no()));
        Order order = new Order();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //设置付款时间
        LocalDateTime fkTime = LocalDateTime.parse(aliPayResponse.getGmt_create(),formatter);
        //订单参数
        order.setOrderNo(aliPayResponse.getOut_trade_no())
                .setOrderStatue(OrderStatue.WAITRIGHT)
                .setOrderFkTime(fkTime)
                .setOrderRealPrice(new BigDecimal(aliPayResponse.getTotal_amount()));
        //更新订单信息
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no",aliPayResponse.getOut_trade_no());
        orderService.update(order,wrapper);
    }

    @RequiresAuthentication
    @GetMapping("/cancel")
    public void cancelOrder(){
        //关闭轮询
        scheduledTask.stop(1);
    }
}
